<template>
<view class="page-tourline-choose-sku">
  <basic-nav-bar 
    left-icon="arrowleft" 
    title="选择套餐和人数" 
    statusBar
    :fixed="true">
  </basic-nav-bar>
  <view class="tourline-choose-sku">
    <sku-calendar
      v-model="chooseDate"
      :enabledDates="enabledDates"
      @change="handleDateChange">
    </sku-calendar>

    <!-- 套餐 -->
    <sku-package
      v-if="simplePkgList && simplePkgList.length" 
      :pkgIndex="curPackageIndex"
      :packageList="simplePkgList"
      @change="handlePackageClick" />

    <!-- 场次 -->
    <sku-round v-if="roundList && roundList.length" v-model="roundIndex" :roundList="roundList" />

    <!-- 规格与数量 -->
    <sku-number v-if="normList && normList.length" :normList="normList" @change="handleNormChange"/>

    <basic-safe-area />
  </view>

  <!-- 预订按钮 -->
  <view class="next-step-pannel">
    <view class="next-step-btn">
      <view class="price-wrapper">
        <basic-price :price="totalPrice" size="36rpx" weight="600" color="#FF5944" unitColor="#FF5944"/>
        <text class="price-detail-trigger" @click="showPriceDetail = true">费用明细</text>
      </view>
      <basic-button type="primary" borderRadius="0" width="240rpx" height='100%' @click="goNextStep">下一步</basic-button>
    </view>
    <basic-safe-area />
  </view>
  
  <!-- 费用明细 -->
  <basic-bottom-popover
    v-model="showPriceDetail"
    :z-index="1"
    title="费用明细">
    <view class="price-detail-popover-content">
      <sku-price-detail :normList="normList" :totalPrice="totalPrice"/>
      <basic-safe-area />
    </view>
  </basic-bottom-popover>
</view>
</template>
<script>
import skuCalendar from '../../../components/sku-calendar'
import skuNumber from '../../../components/sku-number'
import skuRound from '../../../components/sku-round'
import skuPackage from '../../../components/sku-package'
import skuPriceDetail from '../../../components/sku-price-detail'
import storage from 'utils/helper/storage'
import {sortByKey} from 'utils/helper/common'
import {dateFormat} from 'utils/helper/date-handle'
import {cent2Yuan} from '@/filter/filters'
import {decodeQueryObject} from 'utils/helper/query'
import math from 'utils/helper/math'
import modal from 'utils/helper/modal'
import ua from 'utils/ua'
import store from '@/store'
import sdk from 'sdk'
import {getBookCheck} from 'api'

const CACHE_PACKAGE_ENABLEDATES = {} // 缓存套餐日历价格（跟随套餐变化）
const CACHE_PACKAGE_ROUND_LIST = {} // 缓存套餐场次归类sku列表（跟随套餐变化）
const CACHE_PACKAGE_ROUND_LIST_SKU = {} // 缓存以套餐场次为key的sku（跟随套餐变化）

export default {
  name: 'page-tourline-choose-sku',
  components: { skuCalendar, skuNumber, skuRound, skuPackage, skuPriceDetail },

  data() {
    return {
      normList: [],
      roundIndex: 0, // 场次索引
      roundList: [], // 场次列表
      roundListSku: {}, // 以场次名称为key的对象
      packageReleases: [], // 套餐列表
      minPrice: 0, // 线路详情最低价
      
      curPackageIndex: 0, // 当前选中的套餐索引
      chooseDate: '', // dateFormat(new Date())
      enabledDates: null, // 可定日期

      showCalendar: true, // 是否显示日历
      showPriceDetail: false // 是否显示价格明细
    }
  },

  computed: {
    totalPrice() {
      return this.normList.reduce((total, item, index) => {
        total +=  math.multiply(item.price, item.chooseNum) 

        return total
      }, 0)
    },
    simplePkgList() {
      return this.packageReleases.map(item => ({
        name: item.name
      }))
    }
  },

  onLoad(query) {
    this.getData()
		const options = decodeQueryObject(query)
    const { mToken } = options
		if(mToken) store.commit('SAVE_TOKEN', { token: mToken })
  },

  watch: {
    curPackageIndex(val) {
      // 更新日历价格
      this.updateEnableDate(this.packageReleases[val])
      // 更新场次列表
      this.updateRoundList(this.packageReleases[val])
    }
  },

  methods: {
    getData() {
      let cacheTourlineInfo = storage.get('tourline_choose_sku')

      if (!cacheTourlineInfo || !cacheTourlineInfo.tourCode || !cacheTourlineInfo.tourDetail) {
        uni.showToast({
          title: '抱歉，获取线路信息失败',
          icon: 'none',
          duration: '2000'
        })

        setTimeout(() => {sdk.navigateBack()}, 2000)
        return
      }

      this.packageReleases = cacheTourlineInfo.tourDetail.packageReleases

      this.minPrice = cacheTourlineInfo.tourDetail.price

      // 更新日历价格
      this.updateEnableDate(this.packageReleases[this.curPackageIndex])
      // 更新场次列表
      this.updateRoundList(this.packageReleases[this.curPackageIndex])
    },

    handleDateChange(val) {
      this.chooseDate = val.fulldate

      this.showCalendar = false

      this.updateNormList(this.packageReleases[this.curPackageIndex].skuReleases)
    },

    handlePackageClick(index) {
      this.curPackageIndex = index
    },

    /**
     *获取当天最低价
     * 第一个最低预订数大于0且有库存的单价
     * 若全部没有限制最小预订数则取最低价格且可单独购买的sku
     */
    getMinPrice(dateSkus) {
      let targetSkus = dateSkus.filter(dateSku => dateSku.minBookNum >= 1 && dateSku.inventoryNum !== 0)

      if (targetSkus.length) { // 寻找配置了最少可预定数的sku
        return cent2Yuan(targetSkus.reduce((total, sku) => {
          return math.add(total, sku.price * sku.minBookNum)
        }, 0))
      } else { // 没有任何sku配置了最小可预订数，则选择价格最低的
        let min
        dateSkus.forEach(sku => {
          // 排除掉不可单独购买的sku
          if (sku.isOnly != 1) {
            min = min ? Math.min(sku.price, min) : sku.price
          }
        })
        return cent2Yuan(min)
      }
    },
    

    /**
     * 更新可订日期
     */
    updateEnableDate(curPackage) {
      if (CACHE_PACKAGE_ENABLEDATES[curPackage.code]) {
        this.enabledDates = CACHE_PACKAGE_ENABLEDATES[curPackage.code]
        return
      }

      let skuReleases = curPackage.skuReleases || []
      let skuByDates = {}
      
      skuReleases.forEach(sku => {
        sku.inventoryReleases && sku.inventoryReleases.forEach((inventoryItem) => {
          let tempItem = {
            ...inventoryItem,
            maxBookNum: sku.maxBookNum,
            minBookNum: sku.minBookNum,
            isOnly: sku.isOnly
          }

          if (skuByDates[inventoryItem.startDate]) {
            skuByDates[inventoryItem.startDate].push(tempItem)
          } else {
            skuByDates[inventoryItem.startDate] = [tempItem]
          }
        })
      })

      // 重新梳理价格
      let enabledDates = {}
      // let minPrice = cent2Yuan(this.minPrice)
      for(let dateStr in skuByDates) {
        enabledDates[dateStr] = '￥' + this.getMinPrice(skuByDates[dateStr]) + '起'
        // enabledDates[dateStr] = '￥' + minPrice + '起'
      }

      this.enabledDates = enabledDates
    },

    /**
     * 更新sku列表
     */
    updateRoundList(curPackage) {
      let tempRoudObj = {}
      let newRoundList = []
      let skuReleases = curPackage.skuReleases || []

      if (CACHE_PACKAGE_ROUND_LIST[curPackage.code]) {
        this.roundList = CACHE_PACKAGE_ROUND_LIST[curPackage.code]
        this.roundListSku = CACHE_PACKAGE_ROUND_LIST_SKU[curPackage.code]
      } else {
        // [mark]从ubd抄过来的逻辑
        skuReleases.forEach(sku => {
          if(sku.timeSlots){
            sku.timeSlots.map(round => {
              if(!tempRoudObj[round.name]) tempRoudObj[round.name] = []
              
              tempRoudObj[round.name].push(sku)
              newRoundList.push(round)
            })
          }
        })

        // 没有场次信息的sku插入所有场次
        skuReleases.forEach(sku => {
          if(!sku.timeSlots){
            
            for (const roundName in tempRoudObj) {
              tempRoudObj[roundName].push(sku)
            }
          }
        })

        // 对象数组去重
        var temp = {};
        newRoundList = newRoundList.reduce((prev, curv) => {
          // 如果临时对象中有这个名字，什么都不做
          if (temp[curv.name]) {
          }
          // 如果临时对象没有就把这个名字加进去，同时把当前的这个对象加入到prev中
          else {
            temp[curv.name] = true
            prev.push(curv)
          }
          return prev
        }, [])

        this.roundList = sortByKey(newRoundList,'nameFormat') 
        this.roundListSku = tempRoudObj 
      }

      if (this.roundList.length) { // 如果有场次
        this.updateNormList(this.roundListSku[this.roundList[this.roundIndex].name])
      } else {
        this.updateNormList(skuReleases)
      }
    },

    updateNormList(skuReleases) {
      this.normList = []
      // 未选中日期则不显示规格列表
      if (!this.chooseDate) {
        return
      }

      let date = this.chooseDate ? this.chooseDate : ''
      var startDate = date + ' 00:00:00'
      
      let newNormList = []
      for (let index = 0; index < skuReleases.length; index++) {
        let inventoryReleases = skuReleases[index].inventoryReleases ? skuReleases[index].inventoryReleases : []

        let targetRelease = inventoryReleases.find(releaseItem => releaseItem.startDate === startDate)

        if (!targetRelease || !targetRelease.price) continue

        let normItem = {
          code: skuReleases[index].code,
          name: skuReleases[index].name,
          remark: skuReleases[index].remark,
          maxNum: skuReleases[index].maxBookNum, // 限购数（该值用来显示“该商品限购x件”，所以，需要为maxBookNum的原始值）
          maxBookNum: skuReleases[index].maxBookNum, // 最大可预订数（该值用来限定steper的自增上限）
          minBookNum: skuReleases[index].minBookNum, // 最小可预订数（该值用来限定steper的递减下限）
          inventoryNum: targetRelease.inventoryNum,
          price: targetRelease.price,
          isOnly: skuReleases[index].isOnly, // 是否可单独预订
          chooseNum: 0
        }

        // [mark]从ubd抄过来的逻辑
        // inventoryNum :-1 不限制库存  0: 库存为0
        // maxBookNum :-1 不可订  0: 不限制最大可订
        if(normItem.inventoryNum > 0){ //限制库存
            if(normItem.maxBookNum === 0 || normItem.inventoryNum < normItem.maxBookNum){ //不限制最大可定 或 最大可订超过库存
              normItem.maxBookNum = normItem.inventoryNum
            }
        } else if (normItem.inventoryNum < 0) { //不限制库存
          normItem.inventoryNum = 999999
          if(normItem.maxBookNum > 0 && normItem.minBookNum && normItem.maxBookNum < normItem.minBookNum){ //最小可定大于最大可定，不可订
            normItem.maxBookNum = -1
          } else if (normItem.maxBookNum === 0) { // 不限制最大可订
            normItem.maxBookNum = 999999
          }
        } else { // 无库存
          normItem.maxBookNum = -1
        }

        // 初始化选择数
        if(normItem.minBookNum) {
          normItem.chooseNum = normItem.minBookNum
        }
        
        if(normItem.maxBookNum > -1 ){
          newNormList.push(normItem)
        }
      }
      this.normList = newNormList
    },

    /**
     * 检查sku是否存在不可单独预订的sku被单独预订
     * @return {Boolean} true: 不可单独预订的sku被单独预订
     */
    hitAloneSku() {
      let hit = false
      let choosenSkus = this.normList.filter(norm => norm.chooseNum > 0)

      /**
       * isOnly 1:不可单独预订 2:可单独预订
       */
      if (choosenSkus.length === 1 && choosenSkus[0].isOnly == 1) {
        hit = true

        modal.toast(`${choosenSkus[0].name}不可单独预订`)
      }

      return hit
    },

    /**
     * 下一步
     */
    goNextStep() {
      // 日期检查
      if (!this.chooseDate) {
        modal.toast('请先选择日期')
        return
      }

      // 规格检查
      let selectedNorm = this.normList.filter((norm) => norm.chooseNum > 0)

      if (selectedNorm.length <= 0) {
        modal.toast('请选择规格')
        return
      }

      // 单独预订了某个不可以单独预订的sku
      if (this.hitAloneSku()) return

      // 获取预订参数
      let round = this.roundList.length ? this.roundList[this.roundIndex].name : ''
      let bookCheckProductSearchs = selectedNorm.map(norm => {
        let item = {
          code: norm.code,
          num: norm.chooseNum
        }

        if (round) {
          item.specRound = round
        }

        return item
      })

      // 检查是否可订
      let bookInfo = {
        checkin: this.chooseDate,
        bookCheckProductSearchs
      }
      getBookCheck(bookInfo).then(res => {
        // 本地缓存sku数据
        storage.set('fill_order_sku', bookInfo)

        // TODO待优化
        if (ua.isAppWebview) {
          // 为了防止app中支付页面返回订单填写页，需要该页面和订单填写页共享同一个窗口
          uni.navigateTo({
            url: '/packageOrder/pages/fill-order-info/index'
          })
        } else {
          sdk.navigateTo({
            url: '/packageOrder/pages/fill-order-info/index'
          })
        }
      }).catch(_ => {})
    },
    /**
     * 修改规格数量（小程序无法在子组件修改父组件传入的对象属性）
     */
    handleNormChange(e = {}) {
      let {value, index} = e

      this.normList[index].chooseNum = value

      this.hitAloneSku()
    }
  }
}
</script>
<style lang="less">
@booking_height: 100rpx;
.page-tourline-choose-sku {
  background: #ffffff;
  min-height: 100vh;

  .tourline-choose-sku {
    width: 100%;
    padding-bottom: @booking_height;
  }
  
  /deep/ .sku-choose-block {
    background-color: #fff;
    padding: 30rpx;
    border-bottom: 1rpx solid @border_color;

    .sku-choose-block-title {
      font-size: 32rpx;
      font-weight: 600;
      height:46rpx;
      line-height:46rpx;
    }
  }

  .next-step-pannel {
    position: fixed;
    z-index: 2;
    bottom: 0;
    width: 100%;
    background: #fff;
    box-shadow: 0 0 14rpx 0 rgba(204, 204, 204, 0.5);

    .next-step-btn {
      .flex;
      height: @booking_height;
    }
    .price-wrapper {
      .flex-1;
      .flex;
      .flex-middle;

      margin: 0 36rpx;
    }

    .price-detail-trigger {
      margin-left: 20rpx;

      font-size: 24rpx;
      color: @font_desc_color;
      text-decoration: underline;
    }
  }

  .price-detail-popover-content {
    position: relative;
    z-index: 0;
    margin-bottom: @booking_height;
  }
}

</style>